package com.cee.admin.modules.cockpit.controller;

import com.cee.admin.common.BaseController;
import com.cee.admin.common.utils.MapCoordinateUtil;
import com.cee.common.utils.CollectionUtils;
import com.cee.common.web.result.Result;
import com.cee.domain.common.entity.BasePrincipal;
import com.cee.domain.modules.cfd.entity.CfdCarbonFootprintCertificateReport;
import com.cee.domain.modules.cfd.entity.CfdCarbonNeutrality;
import com.cee.domain.modules.cfd.entity.CfdCarbonPerformanceEvaluation;
import com.cee.domain.modules.cockpit.vo.EnterpriseStatVo;
import com.cee.domain.modules.cockpit.vo.FrontUserStatVo;
import com.cee.domain.modules.cockpit.vo.ProjectStatVo;
import com.cee.domain.modules.prod.entity.ProdProduct;
import com.cee.domain.modules.prod.vo.ProdProductCountMonthGrowthTrend;
import com.cee.domain.modules.prod.vo.ProdProductDataReportVo;
import com.cee.domain.modules.sys.entity.SysFrontUser;
import com.cee.domain.modules.sys.entity.User;
import com.cee.domain.modules.sys.stat.SysFrontUserProvinceDistribution;
import com.cee.ds.common.enums.ProductIndustry;
import com.cee.ds.common.utils.BasePrincipalUtils;
import com.cee.ds.modules.cfd.service.ICfdCarbonFootprintCertificateReportService;
import com.cee.ds.modules.cfd.service.ICfdCarbonNeutralityService;
import com.cee.ds.modules.cfd.service.ICfdCarbonPerformanceEvaluationService;
import com.cee.ds.modules.ece.service.IEceReportService;
import com.cee.ds.modules.ece.service.IIndustrialParksService;
import com.cee.ds.modules.pro.service.IProReportService;
import com.cee.ds.modules.prod.service.IProdProductDataReportService;
import com.cee.ds.modules.prod.service.IProdProductService;
import com.cee.ds.modules.sys.service.ISysFrontUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * <p>
 *
 * @author hys
 * @since 2024/4/16 10:38
 */
@RestController
@RequestMapping("/api/cockpit")
@Tag(name = "驾驶舱")
public class CockpitController extends BaseController {

    @Autowired
    private IEceReportService eceReportService;

    @Autowired
    private IProReportService proReportService;

    @Autowired
    private IProdProductService iProdProductService;

    @Autowired
    private IProdProductDataReportService iProdProductDataReportService;

    @Autowired
    private ISysFrontUserService iSysFrontUserService;

    @Autowired
    private ICfdCarbonNeutralityService iCfdCarbonNeutralityService;

    @Autowired
    private ICfdCarbonPerformanceEvaluationService iCfdCarbonPerformanceEvaluationService;

    @Autowired
    private ICfdCarbonFootprintCertificateReportService iCfdCarbonFootprintCertificateReportService;

    @GetMapping("/data/count")
    @Operation(summary = "数据量统计")
    public Result<Map<String, Object>> dataCount(Integer provinceId, Integer cityId, Integer areaId) {
        cityId = Optional.ofNullable(currentUserCityId()).orElse(cityId);
        List<Long> userIds = getUserListByProvinceId(provinceId, cityId, areaId);
        Map<String, Object> result = new HashMap<>(4);
        result.put("productCount", iProdProductService.lambdaQuery().in(userIds != null, ProdProduct::getBelongUser, userIds).count());
        return success(result);
    }

    /**
     * 根据省id获取前台用户id集合
     *
     * @param provinceId 省id
     * @return 前台用户id集合
     */
    private List<Long> getUserListByProvinceId(Integer provinceId, Integer cityId, Integer areaId) {
        if (provinceId == null && cityId == null && areaId == null) {
            return null;
        }
        List<Long> userIds = iSysFrontUserService.lambdaQuery().select(SysFrontUser::getId)
                .eq(provinceId != null, SysFrontUser::getProvinceId, provinceId)
                .eq(cityId != null, SysFrontUser::getCityId, cityId)
                .eq(areaId != null, SysFrontUser::getAreaId, areaId)
                .list().stream().map(SysFrontUser::getId).collect(Collectors.toList());
        return CollectionUtils.isNotEmpty(userIds) ? userIds : Collections.singletonList(null);
    }

    @GetMapping("/user")
    @Operation(summary = "用户信息统计")
    public Result<FrontUserStatVo> frontUserVo(Integer provinceId, Integer cityId, Integer areaId) {
        return success(iSysFrontUserService.cockpitVo(provinceId, Optional.ofNullable(currentUserCityId()).orElse(cityId), areaId));
    }

    @GetMapping("/userDistribution")
    @Operation(summary = "用户分布")
    public Result<List<SysFrontUserProvinceDistribution>> userDistribution() {
        return success(iSysFrontUserService.distribution());
    }

    @GetMapping("/enterprise")
    @Operation(summary = "企业信息统计")
    public Result<EnterpriseStatVo> enterpriseStat(Integer provinceId, Integer cityId, Integer areaId) {
        return success(eceReportService.cockpitStat(provinceId, Optional.ofNullable(currentUserCityId()).orElse(cityId), areaId));
    }

    @GetMapping("/project")
    @Operation(summary = "项目信息统计")
    public Result<ProjectStatVo> projectStat(Integer provinceId, Integer cityId, Integer areaId) {
        return success(proReportService.cockpitStat(provinceId, Optional.ofNullable(currentUserCityId()).orElse(cityId), areaId));
    }

    @GetMapping("/product/statistics")
    @Operation(summary = "产品统计")
    public Result<Map<String, Object>> productStatistics(Integer provinceId, Integer cityId, Integer areaId) {
        cityId = Optional.ofNullable(currentUserCityId()).orElse(cityId);
        List<Long> userIds = getUserListByProvinceId(provinceId, cityId, areaId);
        Map<String, Object> resultMap = new HashMap<>(16);
        List<ProdProductDataReportVo> reportList = iProdProductDataReportService.unitEmissionRanking(provinceId, cityId, areaId);
        Map<String, Object> exist = new HashMap<>(16);
        List<Map<String, Object>> rank = reportList.stream()
                .map(item -> {
                    exist.put(item.getIndustry(), item.getUnitProductEmissions());
                    Map<String, Object> map = new HashMap<>(16);
                    map.put("name", Objects.requireNonNull(ProductIndustry.getByCode(item.getIndustry())).getName());
                    map.put("value", item.getUnitProductEmissions());
                    return map;
                })
                .collect(Collectors.toList());
        for (ProductIndustry industry : ProductIndustry.values()) {
            if (!exist.containsKey(industry.getCode())) {
                Map<String, Object> otherRank = new HashMap<>(16);
                otherRank.put("name", industry.getName());
                otherRank.put("value", 0.0);
                rank.add(otherRank);
            }
        }
        resultMap.put("rank", rank);
        resultMap.put("neutralityCount", iCfdCarbonNeutralityService.lambdaQuery().in(userIds != null, CfdCarbonNeutrality::getBelongUser, userIds).count());
        resultMap.put("performanceCount", iCfdCarbonPerformanceEvaluationService.lambdaQuery().in(userIds != null, CfdCarbonPerformanceEvaluation::getBelongUser, userIds).count());
        resultMap.put("certificateReportCount", iCfdCarbonFootprintCertificateReportService.lambdaQuery().in(userIds != null, CfdCarbonFootprintCertificateReport::getBelongUser, userIds).count());
        return success(resultMap);
    }

    @GetMapping("/product/total/month/growth/trend")
    @Operation(summary = "产品总量月增长趋势图")
    public Result<List<ProdProductCountMonthGrowthTrend>> productTotalMonthGrowthTrend(Integer provinceId, Integer cityId, Integer areaId) {
        cityId = Optional.ofNullable(currentUserCityId()).orElse(cityId);
        List<ProdProductCountMonthGrowthTrend> prodProductCountMonthGrowthTrends = iProdProductService.productTotalMonthGrowthTrend(provinceId, cityId, areaId);
        boolean[] bitmap = new boolean[13];
        for (ProdProductCountMonthGrowthTrend monthGrowthTrend : prodProductCountMonthGrowthTrends) {
            bitmap[monthGrowthTrend.getMonth().intValue()] = true;
        }
        for (int i = 1; i < bitmap.length; i++) {
            if (!bitmap[i]) {
                ProdProductCountMonthGrowthTrend otherMonth = new ProdProductCountMonthGrowthTrend();
                otherMonth.setMonth((long) i);
                prodProductCountMonthGrowthTrends.add(otherMonth);
            }
        }
        prodProductCountMonthGrowthTrends.sort(Comparator.comparing(ProdProductCountMonthGrowthTrend::getMonth));
        return success(prodProductCountMonthGrowthTrends);
    }


    @GetMapping("/map/info/get")
    @Operation(summary = "获取地图信息")
    public Result<String> getMapInfo(@RequestParam(value = "name") String name) {
        return success(MapCoordinateUtil.get(name));
    }

    private Integer currentUserCityId() {
        BasePrincipal basePrincipal = BasePrincipalUtils.currentPrincipal();
        if (basePrincipal instanceof User) {
            return ((User) basePrincipal).getCityId();
        }
        return null;
    }

}
